home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / Telnet 2.6.1d1 4⁄26⁄94 Folder / Krb / enc_des.c < prev    next >
Text File  |  1994-02-20  |  16KB  |  674 lines

  1. /*-
  2.  * Copyright (c) 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted provided
  6.  * that: (1) source distributions retain this entire copyright notice and
  7.  * comment, and (2) distributions including binaries display the following
  8.  * acknowledgement:     ``This product includes software developed by the
  9.  * University of California, Berkeley and its contributors'' in the
  10.  * documentation or other materials provided with the distribution and in
  11.  * all advertising materials mentioning features or use of this software.
  12.  * Neither the name of the University nor the names of its contributors may
  13.  * be used to endorse or promote products derived from this software without
  14.  * specific prior written permission.
  15.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  16.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  17.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.  */
  19.  
  20. #ifndef lint
  21. static char sccsid[] = "@(#)krb_des.c    5.1 (Berkeley) 2/28/91";
  22. #endif /* not lint */
  23.  
  24. /*
  25.  * Copyright (C) 1990 by the Massachusetts Institute of Technology
  26.  *
  27.  * Export of this software from the United States of America is assumed
  28.  * to require a specific license from the United States Government.
  29.  * It is the responsibility of any person or organization contemplating
  30.  * export to obtain such a license before exporting.
  31.  *
  32.  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
  33.  * distribute this software and its documentation for any purpose and
  34.  * without fee is hereby granted, provided that the above copyright
  35.  * notice appear in all copies and that both that copyright notice and
  36.  * this permission notice appear in supporting documentation, and that
  37.  * the name of M.I.T. not be used in advertising or publicity pertaining
  38.  * to distribution of the software without specific, written prior
  39.  * permission.    M.I.T. makes no representations about the suitability of
  40.  * this software for any purpose.  It is provided "as is" without express
  41.  * or implied warranty.
  42.  */
  43.  
  44. #ifdef MPW
  45. #pragma segment 22
  46. #endif
  47.  
  48. #define    NCSA_ENC
  49.  
  50. #ifdef TN3270
  51. #pragma segment 3270tcp
  52.  
  53. #if !defined(USEDUMP)
  54.     #include "maclib.h"
  55.     #include "termdef.h"
  56.     #include "tn3270funcs.h"
  57.     #include "globals.h"
  58. #else
  59.     #pragma load "tn3270DumpFile"
  60. #endif
  61. #include "telnet.h"
  62. #endif /* TN3270 */
  63.  
  64. #define TELCMDS 1
  65. #define TELOPTS 1
  66.  
  67. #ifdef NCSA_ENC
  68. #include "TelnetHeader.h"
  69. #include "wind.h"
  70. #include "parse.proto.h"
  71. #include <StdIO.h>
  72. #endif
  73.  
  74. #ifdef    __STDC__
  75. #include <stdlib.h>
  76. #endif
  77.  
  78. #include "encrypt.h"
  79. /* #include "key-proto.h" */
  80. /* #include "misc-proto.h" */
  81.  
  82. #include "enc_des.proto.h"
  83. #include "encrypt.proto.h"
  84. #include "desproto.h"
  85. #include "kerberos.proto.h"
  86.  
  87. long encrypt_debug_mode = 0;                /* ... */
  88.  
  89. #define CFB        0
  90. #define OFB        1
  91.  
  92. #define NO_SEND_IV        1
  93. #define NO_RECV_IV        2
  94. #define NO_KEYID        4
  95. #define IN_PROGRESS        (NO_SEND_IV|NO_RECV_IV|NO_KEYID)
  96. #define SUCCESS            0
  97. #define FAILED            -1
  98.  
  99.  
  100. #define KEYFLAG_MASK    03
  101.  
  102. #define KEYFLAG_NOINIT    00
  103. #define KEYFLAG_INIT    01
  104. #define KEYFLAG_OK        02
  105. #define KEYFLAG_BAD        03
  106.  
  107. #define KEYFLAG_SHIFT    2
  108.  
  109. #define SHIFT_VAL(a,b)    (KEYFLAG_SHIFT*((a)+((b)*2)))
  110.  
  111. #define FB64_IV            1
  112. #define FB64_IV_OK        2
  113. #define FB64_IV_BAD        3
  114.  
  115.  
  116. static void fb64_session(CDATA *tw, Session_Key *key, long server, struct fb *fbp);
  117. static long fb64_start(CDATA *tw, struct fb *fbp, long dir, long server);
  118.  
  119. void cfb64_init (CDATA *tw, long server)
  120. {
  121.     #pragma unused (server)
  122.     fb64_init(&tw->fb[CFB]);
  123.     tw->fb[CFB].fb_feed[4] = ENCTYPE_DES_CFB64;
  124.     tw->fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, CFB);
  125.     tw->fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, CFB);
  126. }
  127.  
  128. void ofb64_init (CDATA *tw, long server)
  129. {
  130.     #pragma unused (server)
  131.     
  132.     fb64_init(&tw->fb[OFB]);
  133.     tw->fb[OFB].fb_feed[4] = ENCTYPE_DES_OFB64;
  134.     tw->fb[CFB].streams[0].str_flagshift = SHIFT_VAL(0, OFB);
  135.     tw->fb[CFB].streams[1].str_flagshift = SHIFT_VAL(1, OFB);
  136. }
  137.  
  138. void fb64_init (register struct fb *fbp)
  139. {
  140.     xbzero((void *)fbp, sizeof(*fbp));
  141.     fbp->state[0] = fbp->state[1] = FAILED;
  142.     fbp->fb_feed[0] = IAC;
  143.     fbp->fb_feed[1] = SB;
  144.     fbp->fb_feed[2] = OPT_ENCRYPT;
  145.     fbp->fb_feed[3] = ENCRYPT_IS;
  146. }
  147.  
  148. /*
  149.  * Returns:
  150.  *        -1: some error.     Negotiation is done, encryption not ready.
  151.  *         0: Successful, initial negotiation all done.
  152.  *         1: successful, negotiation not done yet.
  153.  *         2: Not yet.  Other things (like getting the key from
  154.  *            Kerberos) have to happen before we can continue.
  155.  */
  156. long cfb64_start (CDATA *tw, long dir, long server)
  157. {
  158.     return(fb64_start(tw, &tw->fb[CFB], dir, server));
  159. }
  160.  
  161.  
  162. long ofb64_start (CDATA *tw, long dir, long server)
  163. {
  164.     return(fb64_start(tw, &tw->fb[OFB], dir, server));
  165. }
  166.  
  167.  
  168. static long fb64_start (CDATA *tw, struct fb *fbp, long dir, long server)
  169. {
  170.     #pragma unused (server)
  171.     
  172. #ifdef notdef
  173.     Block b;
  174. #endif
  175.     long x;
  176.     unsigned char *p;
  177.     register long state;
  178.  
  179.     switch (dir) {
  180.     case DIR_DECRYPT:
  181.         /*
  182.          * This is simply a request to have the other side
  183.          * start output (our input).  He will negotiate an
  184.          * IV so we need not look for it.
  185.          */
  186.         state = fbp->state[dir-1];
  187.         if (state == FAILED)
  188.             state = IN_PROGRESS;
  189.         break;
  190.  
  191.     case DIR_ENCRYPT:
  192.         state = fbp->state[dir-1];
  193.         if (state == FAILED)
  194.             state = IN_PROGRESS;
  195.         else if ((state & NO_SEND_IV) == 0)
  196.             break;
  197.  
  198.         if (!VALIDKEY(fbp->krbdes_key)) {
  199.             fbp->need_start = 1;
  200.             break;
  201.         }
  202.         state &= ~NO_SEND_IV;
  203.         state |= NO_RECV_IV;
  204.         if (encrypt_debug_mode)
  205.             xprintf(tw, "Creating new feed\r\n");
  206.         /*
  207.          * Create a random feed and send it over.
  208.          */
  209.         des_new_random_key(fbp->temp_feed);
  210.         des_ecb_encrypt((unsigned long *)fbp->temp_feed, (unsigned long *)fbp->temp_feed,
  211.                         fbp->krbdes_sched, 1);
  212.         p = fbp->fb_feed + 3;
  213.         *p++ = ENCRYPT_IS;
  214.         p++;
  215.         *p++ = FB64_IV;
  216.         for (x = 0; x < sizeof(Block); ++x) {
  217.             if ((*p++ = fbp->temp_feed[x]) == IAC)
  218.                 *p++ = IAC;
  219.         }
  220.         *p++ = IAC;
  221.         *p++ = SE;
  222. /*        printsub(">", &fbp->fb_feed[2], p - &fbp->fb_feed[2], tw); ddd */
  223.         net_write(tw->wp, (char *)fbp->fb_feed, p - fbp->fb_feed);
  224.         break;
  225.     default:
  226.         return(FAILED);
  227.     }
  228.     return(fbp->state[dir-1] = state);
  229. }
  230.  
  231. /*
  232.  * Returns:
  233.  *        -1: some error.     Negotiation is done, encryption not ready.
  234.  *         0: Successful, initial negotiation all done.
  235.  *         1: successful, negotiation not done yet.
  236.  */
  237. long cfb64_is (CDATA *tw, unsigned char *data, long cnt)
  238. {
  239.     return(fb64_is(tw, data, cnt, &tw->fb[CFB]));
  240. }
  241.  
  242.  
  243. long ofb64_is (CDATA *tw, unsigned char *data, long cnt)
  244. {
  245.     return(fb64_is(tw, data, cnt, &tw->fb[OFB]));
  246. }
  247.  
  248.  
  249. long fb64_is (CDATA *tw, unsigned char *data, long cnt, struct fb *fbp)
  250. {
  251. #ifdef notdef
  252.     long x;
  253.     Block b;
  254. #endif
  255.     unsigned char *p;
  256.     register long state = fbp->state[DIR_DECRYPT-1];
  257.  
  258.     if (cnt-- < 1)
  259.         goto failure;
  260.  
  261.     switch (*data++) {
  262.     case FB64_IV:
  263.         if (cnt != sizeof(Block)) {
  264.             if (encrypt_debug_mode)
  265.                 xprintf(tw, "CFB64: initial vector failed on size\r\n");
  266.             state = FAILED;
  267.             goto failure;
  268.         }
  269.  
  270.         if (encrypt_debug_mode)
  271.             xprintf(tw, "CFB64: initial vector received\r\n");
  272.  
  273.         if (encrypt_debug_mode)
  274.             xprintf(tw, "Initializing Decrypt stream\r\n");
  275.  
  276.         fb64_stream_iv((void *)data, &fbp->streams[DIR_DECRYPT-1]);
  277.  
  278.         p = fbp->fb_feed + 3;
  279.         *p++ = ENCRYPT_REPLY;
  280.         p++;
  281.         *p++ = FB64_IV_OK;
  282.         *p++ = IAC;
  283.         *p++ = SE;
  284. /*        printsub(">", &fbp->fb_feed[2], p - &fbp->fb_feed[2], tw); ddd */
  285.         net_write(tw->wp, (char *)fbp->fb_feed, p - fbp->fb_feed);
  286.  
  287.         state = fbp->state[DIR_DECRYPT-1] = IN_PROGRESS;
  288.         break;
  289.  
  290.     default:
  291. #ifdef notdef
  292.         if (encrypt_debug_mode) {
  293.             xprintf(tw, "Unknown option type: %d\r\n", *(data-1));
  294.             hexout(data, cnt, "");
  295.             xprintf(tw, "\r\n");
  296.         }
  297. #endif
  298.         /* FALL THROUGH */
  299.     failure:
  300.         /*
  301.          * We failed.  Send an FB64_IV_BAD option
  302.          * to the other side so it will know that
  303.          * things failed.
  304.          */
  305.         p = fbp->fb_feed + 3;
  306.         *p++ = ENCRYPT_REPLY;
  307.         p++;
  308.         *p++ = FB64_IV_BAD;
  309.         *p++ = IAC;
  310.         *p++ = SE;
  311. /*        printsub(">", &fbp->fb_feed[2], p - &fbp->fb_feed[2], tw); ddd */
  312.         net_write(tw->wp, (char *)fbp->fb_feed, p - fbp->fb_feed);
  313.  
  314.         break;
  315.     }
  316.     return(fbp->state[DIR_DECRYPT-1] = state);
  317. }
  318.  
  319. /*
  320.  * Returns:
  321.  *        -1: some error.     Negotiation is done, encryption not ready.
  322.  *         0: Successful, initial negotiation all done.
  323.  *         1: successful, negotiation not done yet.
  324.  */
  325. long cfb64_reply (CDATA *tw, unsigned char *data, long cnt)
  326. {
  327.     return(fb64_reply(tw, data, cnt, &tw->fb[CFB]));
  328. }
  329.  
  330.  
  331. long ofb64_reply (CDATA *tw, unsigned char *data, long cnt)
  332. {
  333.     return(fb64_reply(tw, data, cnt, &tw->fb[OFB]));
  334. }
  335.  
  336.  
  337. long fb64_reply (CDATA *tw, unsigned char *data, long cnt, struct fb *fbp)
  338. {
  339. #ifdef notdef
  340.     long x;
  341.     unsigned char *p;
  342.     Block b;
  343. #endif
  344.     register long state = fbp->state[DIR_ENCRYPT-1];
  345.  
  346.     if (cnt-- < 1)
  347.         goto failure;
  348.  
  349.     switch (*data++) {
  350.     case FB64_IV_OK:
  351.         fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]);
  352.         if (state == FAILED)
  353.             state = IN_PROGRESS;
  354.         state &= ~NO_RECV_IV;
  355.         encrypt_send_keyid(tw, DIR_ENCRYPT, (unsigned char *)"\0", 1, 1);
  356.         break;
  357.  
  358.     case FB64_IV_BAD:
  359.         xbzero(fbp->temp_feed, sizeof(Block));
  360.         fb64_stream_iv(fbp->temp_feed, &fbp->streams[DIR_ENCRYPT-1]);
  361.         state = FAILED;
  362.         break;
  363.  
  364.     default:
  365.         if (encrypt_debug_mode) {
  366.             xprintf(tw, "Unknown option type: %d\r\n", data[-1]);
  367. #ifdef notdef
  368.             hexout(data, cnt, "");
  369.             xprintf(tw, "\r\n");
  370. #endif
  371.         }
  372.         /* FALL THROUGH */
  373.     failure:
  374.         state = FAILED;
  375.         break;
  376.     }
  377.     return(fbp->state[DIR_ENCRYPT-1] = state);
  378. }
  379.  
  380.  
  381. void cfb64_session (CDATA *tw, Session_Key *key, long server)
  382. {
  383.     fb64_session(tw, key, server, &tw->fb[CFB]);
  384. }
  385.  
  386.  
  387. void ofb64_session (CDATA *tw, Session_Key *key, long server)
  388. {
  389.     fb64_session(tw, key, server, &tw->fb[OFB]);
  390. }
  391.  
  392. static void fb64_session (CDATA *tw, Session_Key *key, long server, struct fb *fbp)
  393. {
  394.  
  395.     if (!key || key->type != SK_DES) {
  396.         if (encrypt_debug_mode)
  397.             xprintf(tw, "Can't set krbdes's session key (%d != %d)\r\n",
  398.                    key ? key->type : -1, SK_DES);
  399.         return;
  400.     }
  401.     xbcopy((void *)key->data, (void *)fbp->krbdes_key, sizeof(Block));
  402.  
  403.     fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_ENCRYPT-1]);
  404.     fb64_stream_key(fbp->krbdes_key, &fbp->streams[DIR_DECRYPT-1]);
  405.  
  406.     if (fbp->once == 0) {
  407.         des_set_random_generator_seed((des_cblock *)fbp->krbdes_key);
  408.         fbp->once = 1;
  409.     }
  410.     des_key_sched(fbp->krbdes_key, fbp->krbdes_sched);
  411.     /*
  412.      * Now look to see if krbdes_start() was was waiting for
  413.      * the key to show up.    If so, go ahead an call it now
  414.      * that we have the key.
  415.      */
  416.     if (fbp->need_start) {
  417.         fbp->need_start = 0;
  418.         fb64_start(tw, fbp, DIR_ENCRYPT, server);
  419.     }
  420. }
  421.  
  422.  
  423. /*
  424.  * We only accept a keyid of 0.     If we get a keyid of
  425.  * 0, then mark the state as SUCCESS.
  426.  */
  427. long cfb64_keyid (CDATA *tw, long dir, unsigned char *kp, long *lenp)
  428. {
  429.     return(fb64_keyid(dir, kp, lenp, &tw->fb[CFB]));
  430. }
  431.  
  432. long ofb64_keyid (CDATA *tw, long dir, unsigned char *kp, long *lenp)
  433. {
  434.     return(fb64_keyid(dir, kp, lenp, &tw->fb[OFB]));
  435. }
  436.  
  437. long fb64_keyid (long dir, unsigned char *kp, long *lenp, struct fb *fbp)
  438. {
  439.     register long state = fbp->state[dir-1];
  440.  
  441.     if (*lenp != 1 || (*kp != '\0')) {
  442.         *lenp = 0;
  443.         return(state);
  444.     }
  445.  
  446.     if (state == FAILED)
  447.         state = IN_PROGRESS;
  448.  
  449.     state &= ~NO_KEYID;
  450.  
  451.     return(fbp->state[dir-1] = state);
  452. }
  453.  
  454. void fb64_printsub (unsigned char *data, long cnt, unsigned char * buf, long buflen, unsigned char *type)
  455. {
  456.     char lbuf[32];
  457.     register long i;
  458.     char *cp;
  459.  
  460.     buf[buflen-1] = '\0';                /* make sure it's NULL terminated */
  461.     buflen -= 1;
  462.  
  463.     switch(data[2]) {
  464.     case FB64_IV:
  465.         sprintf(lbuf, "%s_IV", type);
  466.         cp = lbuf;
  467.         goto common;
  468.  
  469.     case FB64_IV_OK:
  470.         sprintf(lbuf, "%s_IV_OK", type);
  471.         cp = lbuf;
  472.         goto common;
  473.  
  474.     case FB64_IV_BAD:
  475.         sprintf(lbuf, "%s_IV_BAD", type);
  476.         cp = lbuf;
  477.         goto common;
  478.  
  479.     default:
  480.         sprintf(lbuf, " %d (unknown)", data[2]);
  481.         cp = lbuf;
  482.     common:
  483.         for (; (buflen > 0) && (*buf = *cp++); buf++)
  484.             buflen--;
  485.         for (i = 3; i < cnt; i++) {
  486.             sprintf(lbuf, " %d", data[i]);
  487.             for (cp = lbuf; (buflen > 0) && (*buf = *cp++); buf++)
  488.                 buflen--;
  489.         }
  490.         break;
  491.     }
  492. }
  493.  
  494. void cfb64_printsub (unsigned char *data, long cnt, unsigned char *buf, long buflen)
  495. {
  496.     fb64_printsub(data, cnt, buf, buflen, (unsigned char *)"CFB64");
  497. }
  498.  
  499. void ofb64_printsub (unsigned char *data, long cnt, unsigned char *buf, long buflen)
  500. {
  501.     fb64_printsub(data, cnt, buf, buflen, (unsigned char *)"OFB64");
  502. }
  503.  
  504. void fb64_stream_iv (Block seed, register struct stinfo *stp)
  505. {
  506.  
  507.     xbcopy((void *)seed, (void *)stp->str_iv, sizeof(Block));
  508.     xbcopy((void *)seed, (void *)stp->str_output, sizeof(Block));
  509.  
  510.     des_key_sched(stp->str_ikey, stp->str_sched);
  511.  
  512.     stp->str_index = sizeof(Block);
  513. }
  514.  
  515. void fb64_stream_key (Block key, register struct stinfo *stp)
  516. {
  517.     xbcopy((void *)key, (void *)stp->str_ikey, sizeof(Block));
  518.     des_key_sched(key, stp->str_sched);
  519.  
  520.     xbcopy((void *)stp->str_iv, (void *)stp->str_output, sizeof(Block));
  521.  
  522.     stp->str_index = sizeof(Block);
  523. }
  524.  
  525. /*
  526.  * DES 64 bit Cipher Feedback
  527.  *
  528.  *       key --->+-----+
  529.  *            +->| DES |--+
  530.  *            |  +-----+    |
  531.  *            |            v
  532.  *    INPUT --(--------->(+)+---> DATA
  533.  *            |              |
  534.  *            +-------------+
  535.  *           
  536.  *
  537.  * Given:
  538.  *        iV: Initial vector, 64 bits (8 bytes) long.
  539.  *        Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt).
  540.  *        On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output.
  541.  *
  542.  *        V0 = DES(iV, key)
  543.  *        On = Dn ^ Vn
  544.  *        V(n+1) = DES(On, key)
  545.  */
  546.  
  547. void cfb64_encrypt (CDATA *tw, register unsigned char *s, long c)
  548. {
  549.     register struct stinfo *stp = &tw->fb[CFB].streams[DIR_ENCRYPT-1];
  550.     register long index;
  551.  
  552.     index = stp->str_index;
  553.     while (c-- > 0) {
  554.         if (index == sizeof(Block)) {
  555.             Block b;
  556.             des_ecb_encrypt((unsigned long *)stp->str_output, (unsigned long *)b, stp->str_sched, 1);
  557.             xbcopy((void *)b, (void *)stp->str_feed, sizeof(Block));
  558.             index = 0;
  559.         }
  560.  
  561.         /* On encryption, we store (feed ^ data) which is cypher */
  562.         *s = stp->str_output[index] = (stp->str_feed[index] ^ *s);
  563.         s++;
  564.         index++;
  565.     }
  566.     stp->str_index = index;
  567. }
  568.  
  569. long cfb64_decrypt (CDATA *tw, long data)
  570. {
  571.     register struct stinfo *stp = &tw->fb[CFB].streams[DIR_DECRYPT-1];
  572.     long index;
  573.  
  574.     if (data == -1) {
  575.         /*
  576.          * Back up one byte.  It is assumed that we will
  577.          * never back up more than one byte.  If we do, this
  578.          * may or may not work.
  579.          */
  580.         if (stp->str_index)
  581.             --stp->str_index;
  582.         return(0);
  583.     }
  584.  
  585.     index = stp->str_index++;
  586.     if (index == sizeof(Block)) {
  587.         Block b;
  588.         des_ecb_encrypt((unsigned long *)stp->str_output, (unsigned long *)b, stp->str_sched, 1);
  589.         xbcopy((void *)b, (void *)stp->str_feed, sizeof(Block));
  590.         stp->str_index = 1;                /* Next time will be 1 */
  591.         index = 0;                        /* But now use 0 */ 
  592.     }
  593.  
  594.     /* On decryption we store (data) which is cypher. */
  595.     stp->str_output[index] = data;
  596.     return(data ^ stp->str_feed[index]);
  597. }
  598.  
  599. /*
  600.  * DES 64 bit Output Feedback
  601.  *
  602.  * key --->+-----+
  603.  *        +->| DES |--+
  604.  *        |  +-----+    |
  605.  *        +-----------+
  606.  *                    v
  607.  *    INPUT -------->(+) ----> DATA
  608.  *
  609.  * Given:
  610.  *        iV: Initial vector, 64 bits (8 bytes) long.
  611.  *        Dn: the nth chunk of 64 bits (8 bytes) of data to encrypt (decrypt).
  612.  *        On: the nth chunk of 64 bits (8 bytes) of encrypted (decrypted) output.
  613.  *
  614.  *        V0 = DES(iV, key)
  615.  *        V(n+1) = DES(Vn, key)
  616.  *        On = Dn ^ Vn
  617.  */
  618. void ofb64_encrypt (CDATA *tw, register unsigned char *s, long c)
  619. {
  620.     register struct stinfo *stp = &tw->fb[OFB].streams[DIR_ENCRYPT-1];
  621.     register long index;
  622.  
  623.     index = stp->str_index;
  624.     while (c-- > 0) {
  625.         if (index == sizeof(Block)) {
  626.             Block b;
  627.             des_ecb_encrypt((unsigned long *)stp->str_feed, (unsigned long *)b, stp->str_sched, 1);
  628.             xbcopy((void *)b, (void *)stp->str_feed, sizeof(Block));
  629.             index = 0;
  630.         }
  631.         *s++ ^= stp->str_feed[index];
  632.         index++;
  633.     }
  634.     stp->str_index = index;
  635. }
  636.  
  637. long ofb64_decrypt (CDATA *tw, long data)
  638. {
  639.     register struct stinfo *stp = &tw->fb[OFB].streams[DIR_DECRYPT-1];
  640.     long index;
  641.  
  642.     if (data == -1) {
  643.         /*
  644.          * Back up one byte.  It is assumed that we will
  645.          * never back up more than one byte.  If we do, this
  646.          * may or may not work.
  647.          */
  648.         if (stp->str_index)
  649.             --stp->str_index;
  650.         return(0);
  651.     }
  652.  
  653.     index = stp->str_index++;
  654.     if (index == sizeof(Block)) {
  655.         Block b;
  656.         des_ecb_encrypt((unsigned long *)stp->str_feed, (unsigned long *)b, stp->str_sched, 1);
  657.         xbcopy((void *)b, (void *)stp->str_feed, sizeof(Block));
  658.         stp->str_index = 1;                /* Next time will be 1 */
  659.         index = 0;                        /* But now use 0 */ 
  660.     }
  661.  
  662.     return(data ^ stp->str_feed[index]);
  663. }
  664.  
  665.  
  666. /*
  667.  * printd
  668.  * dummy routine
  669.  */
  670. void printd (unsigned char *data, long cnt)
  671. {
  672.     #pragma unused (data, cnt)
  673. }
  674.